package fr.upmf.ic2a.sharedata.provider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Log;

public class ShareDataProvider extends ContentProvider {

	// Creates a UriMatcher object.
	private static final UriMatcher sUriMatcher;
	private static final int CONTACT = 1;
	private static final int CONTACT_ID = 2;
	private static final int SENT = 3;
	private static final int SENT_ID = 4;
	private static final int SENT_ID_CONTACT = 5;
	private static final int RECEIVED = 6;
	private static final int RECEIVED_ID = 7;
	private static final int FILE = 8;
	private static final int FILE_ID = 9;

	private static final String TAG = "ShareDataProvider";
	private static final String DATABASE_NAME = "shareData.db";
	private static final int DATABASE_VERSION = 1;
	private static DbOpenHelper dbHelper;

	static {
		sUriMatcher = new UriMatcher(0);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "contacts", CONTACT);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "contacts/#",
				CONTACT_ID);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "sent", SENT);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "sent/#", SENT_ID);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "sent/#/contacts",
				SENT_ID_CONTACT);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "received", RECEIVED);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "received/#",
				RECEIVED_ID);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "file", FILE);
		sUriMatcher.addURI(ShareDataContract.AUTHORITY, "file/#", FILE_ID);
	}

	@Override
	public boolean onCreate() {
		dbHelper = new DbOpenHelper(getContext());
		return true;
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case CONTACT:
			return ShareDataContract.Contact.CONTENT_TYPE;
		case CONTACT_ID:
			return ShareDataContract.Contact.CONTENT_ITEM_TYPE;
		case SENT:
			return ShareDataContract.Sent.CONTENT_TYPE;
		case SENT_ID:
			return ShareDataContract.Sent.CONTENT_ITEM_TYPE;
		case SENT_ID_CONTACT:
			;
		case RECEIVED:
			return ShareDataContract.Received.CONTENT_TYPE;
		case RECEIVED_ID:
			return ShareDataContract.Received.CONTENT_ITEM_TYPE;
		case FILE:
			return ShareDataContract.File.CONTENT_TYPE;
		case FILE_ID:
			return ShareDataContract.File.CONTENT_ITEM_TYPE;
		}
		return null;
	}

	private long getId(Uri uri) {
		String lastPathSegment = uri.getLastPathSegment();
		switch (sUriMatcher.match(uri)) {
		case CONTACT:
			return -1;
		case CONTACT_ID:
			if (lastPathSegment != null) {
				try {
					return Long.parseLong(lastPathSegment);
				} catch (NumberFormatException e) {
					Log.e("ShareDataProvider", "Number Format Exception : " + e);
				}
			}
		case SENT:
			return -1;
		case SENT_ID:
			if (lastPathSegment != null) {
				try {
					return Long.parseLong(lastPathSegment);
				} catch (NumberFormatException e) {
					Log.e("ShareDataProvider", "Number Format Exception : " + e);
				}
			}
		case SENT_ID_CONTACT:
			String beforelastPathSegment = uri.getPathSegments().get(uri.getPathSegments().size()-2);
			if (beforelastPathSegment != null) {
				try {
					return Long.parseLong(beforelastPathSegment);
				} catch (NumberFormatException e) {
					Log.e("ShareDataProvider", "Number Format Exception : " + e);
				}
			};
		case RECEIVED:
			return -1;
		case RECEIVED_ID:
			if (lastPathSegment != null) {
				try {
					return Long.parseLong(lastPathSegment);
				} catch (NumberFormatException e) {
					Log.e("ShareDataProvider", "Number Format Exception : " + e);
				}
			}
		case FILE:
			return -1;
		case FILE_ID:
			if (lastPathSegment != null) {
				try {
					return Long.parseLong(lastPathSegment);
				} catch (NumberFormatException e) {
					Log.e("ShareDataProvider", "Number Format Exception : " + e);
				}
			}
		default:
			return -1;
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {

		SQLiteDatabase db = dbHelper.getWritableDatabase();

		switch (sUriMatcher.match(uri)) {
		case SENT:
			try {
				long id = db.insertOrThrow(ShareDataContract.Sent.TABLE_NAME,
						null, values);
				if (id == -1) {
					throw new RuntimeException(String.format(
							"%s : Failed to insert [%s] for unknown reasons.",
							"ShareDataProvider", values, uri));
				} else {
					return ContentUris.withAppendedId(uri, id);
				}
			} finally {
				db.close();
			}
		case CONTACT:
			try {
				long id = db.insertOrThrow(
						ShareDataContract.Contact.TABLE_NAME, null, values);
				if (id == -1) {
					throw new RuntimeException(String.format(
							"%s : Failed to insert [%s] for unknown reasons.",
							"ShareDataProvider", values, uri));
				} else {
					return ContentUris.withAppendedId(uri, id);
				}
			} finally {
				db.close();
			}
		case RECEIVED:
			try {
				long id = db.insertOrThrow(
						ShareDataContract.Received.TABLE_NAME, null, values);
				if (id == -1) {
					throw new RuntimeException(String.format(
							"%s : Failed to insert [%s] for unknown reasons.",
							"ShareDataProvider", values, uri));
				} else {
					return ContentUris.withAppendedId(uri, id);
				}
			} finally {
				db.close();
			}
		case FILE:
			try {
				long id = db.insertOrThrow(ShareDataContract.File.TABLE_NAME,
						null, values);
				if (id == -1) {
					throw new RuntimeException(String.format(
							"%s : Failed to insert [%s] for unknown reasons.",
							"ShareDataProvider", values, uri));
				} else {
					return ContentUris.withAppendedId(uri, id);
				}
			} finally {
				db.close();
			}
		}
		return null;
	}

	@Override
	public int delete(Uri uri, String where, String[] whereArgs) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case CONTACT:
			count = db.delete(ShareDataContract.Contact.TABLE_NAME, where,
					whereArgs);
			break;

		case CONTACT_ID:
			String contactId = uri.getPathSegments().get(1);
			count = db.delete(ShareDataContract.Contact.TABLE_NAME,
					ShareDataContract.Contact._ID
							+ "="
							+ contactId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
			break;
		case SENT:
			count = db.delete(ShareDataContract.Sent.TABLE_NAME, where,
					whereArgs);
			break;
		case SENT_ID:
			String sentId = uri.getPathSegments().get(1);
			count = db.delete(
					ShareDataContract.Sent.TABLE_NAME,
					ShareDataContract.Sent._ID
							+ "="
							+ sentId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		case SENT_ID_CONTACT:
			String sentIdContact = uri.getPathSegments().get(1);
			count = db.delete(ShareDataContract.Contact.TABLE_NAME,
					ShareDataContract.Contact.ID_SENT
							+ "="
							+ sentIdContact
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		case RECEIVED:
			count = db.delete(ShareDataContract.Received.TABLE_NAME, where,
					whereArgs);
			break;
		case RECEIVED_ID:
			String receiveId = uri.getPathSegments().get(1);
			count = db.delete(ShareDataContract.Received.TABLE_NAME,
					ShareDataContract.Received._ID
							+ "="
							+ receiveId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		case FILE:
			count = db.delete(ShareDataContract.File.TABLE_NAME, where,
					whereArgs);
			break;
		case FILE_ID:
			String fileId = uri.getPathSegments().get(1);
			count = db.delete(
					ShareDataContract.File.TABLE_NAME,
					ShareDataContract.File._ID
							+ "="
							+ fileId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	@Override
	public int update(Uri uri, ContentValues values, String where,
			String[] whereArgs) {
		SQLiteDatabase db = dbHelper.getWritableDatabase();
		int count;
		switch (sUriMatcher.match(uri)) {
		case CONTACT:
			count = db.update(ShareDataContract.Contact.TABLE_NAME, values,
					where, whereArgs);
			break;
		case CONTACT_ID:
			String contactId = uri.getPathSegments().get(1);
			count = db.update(ShareDataContract.Contact.TABLE_NAME, values,
					ShareDataContract.Contact._ID
							+ "="
							+ contactId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
			break;
		case SENT:
			count = db.update(ShareDataContract.Sent.TABLE_NAME, values, where,
					whereArgs);
			break;
		case SENT_ID:
			String sentId = uri.getPathSegments().get(1);
			count = db.update(
					ShareDataContract.Sent.TABLE_NAME,
					values,
					ShareDataContract.Sent._ID
							+ "="
							+ sentId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		case SENT_ID_CONTACT:
			String sentIdContact = uri.getPathSegments().get(1);
			count = db.update(ShareDataContract.Contact.TABLE_NAME, values,
					ShareDataContract.Contact.ID_SENT
							+ "="
							+ sentIdContact
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		case RECEIVED:
			count = db.update(ShareDataContract.Received.TABLE_NAME, values,
					where, whereArgs);
			break;
		case RECEIVED_ID:
			String receiveId = uri.getPathSegments().get(1);
			count = db.update(ShareDataContract.Received.TABLE_NAME, values,
					ShareDataContract.Received._ID
							+ "="
							+ receiveId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		case FILE:
			count = db.update(ShareDataContract.File.TABLE_NAME, values, where,
					whereArgs);
			break;
		case FILE_ID:
			String fileId = uri.getPathSegments().get(1);
			count = db.update(
					ShareDataContract.File.TABLE_NAME,
					values,
					ShareDataContract.File._ID
							+ "="
							+ fileId
							+ (!TextUtils.isEmpty(where) ? " AND (" + where
									+ ')' : ""), whereArgs);
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

		getContext().getContentResolver().notifyChange(uri, null);
		return count;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {

		long id = getId(uri);
		SQLiteDatabase db = dbHelper.getReadableDatabase();

		switch (sUriMatcher.match(uri)) {
		case CONTACT:
			if (id < 0) {
				return db.query(ShareDataContract.Contact.TABLE_NAME,
						projection, selection, selectionArgs, null, null,
						sortOrder);
			} else {
				// Gestion d'erreur
			}
		case CONTACT_ID:
			if (id < 0) {
				// Gestion d'erreur
			} else {
				return db.query(ShareDataContract.Contact.TABLE_NAME,
						projection, ShareDataContract.Sent._ID + "=" + id,
						null, null, null, null);
			}
		case SENT:
			if (id < 0) {
				return db.query(ShareDataContract.Sent.TABLE_NAME, projection,
						selection, selectionArgs, null, null, sortOrder);
			} else {
				// Gestion d'erreur
			}
		case SENT_ID:
			if (id < 0) {
				// Gestion d'erreur
			} else {
				return db.query(ShareDataContract.Sent.TABLE_NAME, projection,
						ShareDataContract.Sent._ID + "=" + id, null, null,
						null, null);
			}
		case SENT_ID_CONTACT:
			if (id < 0) {
				// Gestion d'erreur
			} else {
				return db.query(ShareDataContract.Sent.TABLE_NAME, projection,
						ShareDataContract.Contact.ID_SENT + "=" + id, null,
						null, null, null);
			}
		case RECEIVED:
			if (id < 0) {
				return db.query(ShareDataContract.Received.TABLE_NAME,
						projection, selection, selectionArgs, null, null,
						sortOrder);
			} else {
				// Gestion d'erreur
			}
		case RECEIVED_ID:
			if (id < 0) {
				// Gestion d'erreur
			} else {
				return db.query(ShareDataContract.Received.TABLE_NAME,
						projection, ShareDataContract.Received._ID + "=" + id,
						null, null, null, null);
			}
		case FILE:
			if (id < 0) {
				return db.query(ShareDataContract.File.TABLE_NAME, projection,
						selection, selectionArgs, null, null, sortOrder);
			} else {
				// Gestion d'erreur
			}
		case FILE_ID:
			if (id < 0) {
				// Gestion d'erreur
			} else {
				return db.query(ShareDataContract.File.TABLE_NAME, projection,
						ShareDataContract.File._ID + "=" + id, null, null,
						null, null);
			}
		}
		return null;
	}

	private static final class DbOpenHelper extends SQLiteOpenHelper {

		public DbOpenHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL("CREATE TABLE "
					+ ShareDataContract.Sent.TABLE_NAME
					+ " ("
					+ ShareDataContract.Sent._ID
					+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
					+ ShareDataContract.Sent.ID_FILE
					+ " INTEGER,"
					// + " FOREIGN KEY (" + ShareDataContract.Sent.ID_FILE
					// + ") REFERENCES " + ShareDataContract.File.TABLE_NAME
					// + " (" + ShareDataContract.File._ID +
					// " ON DELETE CASCADE)"
					+ ShareDataContract.Sent.TITLE + " VARCHAR(255),"
					+ ShareDataContract.Sent.SYNC_STATUS + " INTEGER" + ");");
			db.execSQL("CREATE TABLE "
					+ ShareDataContract.Received.TABLE_NAME
					+ " ("
					+ ShareDataContract.Received._ID
					+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
					+ ShareDataContract.Received.ID_FILE
					+ " INTEGER,"
					// + " FOREIGN KEY (" + ShareDataContract.Received.ID_FILE
					// + ") REFERENCES " + ShareDataContract.File.TABLE_NAME
					// + " (" + ShareDataContract.File._ID +
					// " ON DELETE CASCADE)"
					+ ShareDataContract.Received.FROM_ID
					+ " INTEGER,"
					// + " FOREIGN KEY (" + ShareDataContract.Received.FROM_ID
					// + ") REFERENCES " + ShareDataContract.Contact.TABLE_NAME
					// + " (" + ShareDataContract.Contact._ID
					// + " ON DELETE CASCADE)"
					+ ShareDataContract.Received.TITLE + " VARCHAR(255),"
					+ ShareDataContract.Received.SYNC_STATUS + " INTEGER);");
			db.execSQL("CREATE TABLE " + ShareDataContract.Contact.TABLE_NAME
					+ " (" + ShareDataContract.Contact._ID
					+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
					+ ShareDataContract.Contact.ID_CONTACT + " INTEGER,"
					+ ShareDataContract.Contact.ID_SENT + " INTEGER"
					// + " FOREIGN KEY (" + ShareDataContract.Contact.ID_SENT
					// + ") REFERENCES " + ShareDataContract.Sent.TABLE_NAME
					// + " (" + ShareDataContract.Sent._ID +
					// " ON DELETE CASCADE)"
					+ ");");
			db.execSQL("CREATE TABLE " + ShareDataContract.File.TABLE_NAME
					+ " (" + ShareDataContract.File._ID
					+ " INTEGER PRIMARY KEY AUTOINCREMENT,"
					+ ShareDataContract.File.MIME_TYPE + " VARCHAR(255), "
					+ ShareDataContract.File.URL_SYSTEM + " VARCHAR(255)"
					+ ");");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS "
					+ ShareDataContract.Sent.TABLE_NAME);
			db.execSQL("DROP TABLE IF EXISTS "
					+ ShareDataContract.Received.TABLE_NAME);
			db.execSQL("DROP TABLE IF EXISTS "
					+ ShareDataContract.Contact.TABLE_NAME);
			db.execSQL("DROP TABLE IF EXISTS "
					+ ShareDataContract.File.TABLE_NAME);
			onCreate(db);
		}

		@Override
		public void onOpen(SQLiteDatabase db) {
			super.onOpen(db);
			if (!db.isReadOnly()) {
				db.execSQL("PRAGMA foreign_keys=ON;");
			}
		}
	}
}
